package com.learn.concurrent.aqs.t1;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author wangxing
 * @version 2020/8/14 22:21 Administrator
 */
public class AqsLearn {
    private static final int BAI = 100;
    private static final int QIAN = 1000;
    private static final int WAN = 10000;
    public static int m = 0;

    public static void runTemp(String methodName) throws NoSuchMethodException, InvocationTargetException,
            IllegalAccessException {

        m = 0;
        Method method = AqsLearn.class.getMethod(methodName, null);
        int count = 0, temp = 0;
        {
            long start = System.currentTimeMillis();
            temp = (int) method.invoke(new AqsLearn(), null);
            while (temp == WAN && count < QIAN) {
                m = 0;
                temp = (int) method.invoke(new AqsLearn(), null);
                count++;
            }
            long end = System.currentTimeMillis();
            System.out.println(methodName + "执行次数:" + count+"; 最后输出值:"+temp+";执行时间:"+(end-start));
        }

    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException
            , InvocationTargetException {
        runTemp("notLock");
        runTemp("haveSynchronized");
        runTemp("haveReenTrantLock");
        runTemp("haveMyWaitLock");
    }

    public static int notLock() throws InterruptedException {
        Thread[] threads = new Thread[100];
        for (int i = 0, l = threads.length; i < l; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < BAI; j++) {
                    m++;
                }
            });
        }
        for (Thread t : threads) {
            t.start();
        }
        for (Thread t : threads) {
            t.join();
        }
        return m;
    }

    public static int haveSynchronized() throws InterruptedException {
        Thread[] threads = new Thread[100];
        for (int i = 0, l = threads.length; i < l; i++) {
            threads[i] = new Thread(() -> {
                synchronized (AqsLearn.class) {
                    for (int j = 0; j < BAI; j++) {
                        m++;
                    }
                }
            });
        }
        for (Thread t : threads) {
            t.start();
        }
        for (Thread t : threads) {
            t.join();
        }

        return m;
    }

    /**
     * AQS
     */
    static Lock lock = new ReentrantLock();

    public static int haveReenTrantLock() throws InterruptedException {
        Thread[] threads = new Thread[100];
        for (int i = 0, l = threads.length; i < l; i++) {
            threads[i] = new Thread(() -> {
                lock.lock();
                try {
                    for (int j = 0; j < BAI; j++) {
                        m++;
                    }
                } finally {
                    lock.unlock();
                }


            });
        }
        for (Thread t : threads) {
            t.start();
        }
        for (Thread t : threads) {
            t.join();
        }

        return m;
    }

    static Lock myLock = new MyWaitLock();

    public static int haveMyWaitLock() throws InterruptedException {
        Thread[] threads = new Thread[100];
        for (int i = 0, l = threads.length; i < l; i++) {
            threads[i] = new Thread(() -> {
                myLock.lock();
                try {
                    for (int j = 0; j < BAI; j++) {
                        m++;
                    }
                } finally {
                    myLock.unlock();
                }
            });
        }
        for (Thread t : threads) {
            t.start();
        }
        for (Thread t : threads) {
            t.join();
        }

//        System.out.println(m);
        return m;
    }
}
